package com.baiyi.homeui.hshomeui.manage;

import android.content.Context;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import android.os.StatFs;

import androidx.annotation.NonNull;

import com.baiyi.homeui.hshomeui.callback.IOnPcControlCallBack;
import com.baiyi.homeui.hshomeui.entity.FanLCD;
import com.baiyi.homeui.hshomeui.entity.PcInfo;
import com.baiyi.homeui.hshomeui.entity.ScreenConfig;
import com.baiyi.homeui.hshomeui.entity.Warning;
import com.baiyi.homeui.hshomeui.util.FileUtil;
import com.baiyi.homeui.hshomeui.util.JsonUtils;
import com.baiyi.homeui.hshomeui.util.SLog;
import com.baiyi.homeui.hshomeui.util.SystemPropertiesUtils;
import com.baiyi.service.serialservice.serialdataservice.IOnSerialDataCallback;
import com.baiyi.service.serialservice.serialdataservice.data.entity.SerialData;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;
import java.util.ArrayList;

public class MsgReceiverManager {

    private String TAG = "MsgReceiverManager";
    private static MsgReceiverManager instance;
    private Context mContext;
    private Handler mReceiverHandler;
    private final int MSG_RECEIVER_DATA = 101;
    private final int MSG_CONNECT_TIMEOUT = 102;


    private String fanPath = "/sys/bus/platform/drivers/lcd_fan/speed";
    private FanLCD fanLCD;

    public boolean displayInSleep = true;

    public boolean isTimeOut = false;

    private boolean isConnect = false;
    public static String temp_unit;
    public  String cpuinfo = "",gpuinfo = "";

    class MsgReceiverLooperThread extends Thread {
        public void run() {
            Looper.prepare();
            mReceiverHandler = new Handler(Looper.myLooper()) {
                @Override
                public void handleMessage(@NonNull Message msg) {
                    super.handleMessage(msg);
                    switch (msg.what) {
                        case MSG_RECEIVER_DATA:
                            SerialData serialData = (SerialData) msg.obj;

                            switch (serialData.getRequestState()) {

                                case SerialData.STATE_STATE:
                                    SLog.d(TAG, "---STATE_STATE---" + serialData.getDataContent());
                                    if (serialData.getCmdType().equals("all")) {
                                        if (mIOnPcControlCallBack != null) {
                                            try {
                                                PcInfo pcInfo = JsonUtils.stringToObject(serialData.getDataContent(), PcInfo.class);
                                                mIOnPcControlCallBack.onRefreshUI(pcInfo);
                                            } catch (Exception e) {
                                                SLog.e(TAG, "all--解析失败--" + e.getMessage());
                                            }
                                            String fanvaule = FileUtil.readFile(fanPath);
                                            JSONObject object = new JSONObject();
                                            JSONObject status = new JSONObject();
                                            try {
                                                status.put("fanLCD", fanvaule);
                                                object.put("status", status);
                                                ArrayList<Warning> warnings = new ArrayList();
                                                warnings.add(new Warning("Fan LCD", "No ERROR"));
                                                object.put("warning", JsonUtils.mGson.toJson(warnings));
                                                object.put("availableStorage",getAvailableStorage());
                                            } catch (JSONException e) {
                                                SLog.d(TAG, "---Exception---" + e.getMessage());
                                                e.printStackTrace();
                                            }
                                            SerialData ackData = new SerialData();
                                            ackData.setVersion("1");
                                            ackData.setCmdType(200 + "");
                                            ackData.setDataContent(object.toString());
                                            int ackNum = serialData.getDataHeader().getSeqNumber();
                                            SerialDataManage.getInstance().sendMsg(ackData, ackNum + 1);
                                        }
                                    }
                                    break;
                                case SerialData.STATE_POST:
                                    SLog.d(TAG, "---STATE_POST---" + serialData.getDataContent());
                                    switch (serialData.getCmdType()) {
                                        case "all":
                                            if (serialData.getCmdType().equals("all")) {
                                                if (mIOnPcControlCallBack != null) {
                                                    PcInfo pcInfo = JsonUtils.stringToObject(serialData.getDataContent(), PcInfo.class);
                                                    mIOnPcControlCallBack.onRefreshUI(pcInfo);
                                                }

                                                String fanvaule = FileUtil.readFile(fanPath);
                                                JSONObject object = new JSONObject();
                                                JSONObject status = new JSONObject();
                                                try {
                                                    status.put("fanLCD", fanvaule);
                                                    object.put("status", status);
                                                } catch (JSONException e) {
                                                    SLog.d(TAG, "---Exception---" + e.getMessage());
                                                    e.printStackTrace();
                                                }
                                                SerialData ackData = new SerialData();
                                                ackData.setVersion("1");
                                                ackData.setCmdType(200 + "");
                                                ackData.setDataContent(object.toString());
                                                int ackNum = serialData.getDataHeader().getSeqNumber();
                                                SerialDataManage.getInstance().sendMsg(ackData, ackNum + 1);


                                            }
                                            break;
                                        case "power":
                                            /*suspend
                                             resume
                                            shutdown
                                            lock-screen
                                            unlock-screen*/
                                            try {
                                                JSONObject jsonObject = new JSONObject(serialData.getDataContent());
                                                String event = jsonObject.getString("event");
                                                doPower(event);
                                            } catch (JSONException e) {
                                                SLog.d(TAG, "---Exception---" + e.getMessage());
                                                e.printStackTrace();
                                            }
                                            break;
                                        case "waterBlockScreen":
                                            try {
                                                JSONObject jsonObject = new JSONObject(serialData.getDataContent());
                                                boolean enable = jsonObject.getBoolean("enable");
                                                doBlockScreen(enable);
                                            } catch (JSONException e) {
                                                SLog.d(TAG, "---Exception---" + e.getMessage());
                                                e.printStackTrace();
                                            }
                                            break;
                                        case "displayInSleep":
                                            try {
                                                JSONObject jsonObject = new JSONObject(serialData.getDataContent());
                                                displayInSleep = jsonObject.getBoolean("enable");

                                            } catch (JSONException e) {
                                                SLog.d(TAG, "---Exception---" + e.getMessage());
                                                e.printStackTrace();
                                            }
                                            break;
                                        case "waterBlockScreenId":
                                            ScreenConfig config = JsonUtils.stringToObject(serialData.getDataContent(), ScreenConfig.class);
                                            if (mIOnPcControlCallBack != null) {
                                                mIOnPcControlCallBack.screenConfigChange(config);
                                            }
                                            break;
                                        case "preset":
                                            ScreenConfig presetconfig = JsonUtils.stringToObject(serialData.getDataContent(), ScreenConfig.class);
                                            if (mIOnPcControlCallBack != null) {
                                                mIOnPcControlCallBack.presetConfigChange(presetconfig);
                                            }
                                            break;
                                        case "disconn":
                                            if (mIOnPcControlCallBack != null) {
                                                mIOnPcControlCallBack.onDisConnect();
                                            }
                                            break;

                                        case "brightness":
                                            try {
                                                JSONObject jsonObject = new JSONObject(serialData.getDataContent());
                                                int brightness = jsonObject.getInt("value");
                                                doBrightness(brightness);
                                            } catch (JSONException e) {
                                                SLog.d(TAG, "brightness JSONException--" + e.getMessage());
                                            }
                                            /*ScreenConfig config3 = new ScreenConfig();
                                            try {
                                                JSONObject object = new JSONObject(serialData.getDataContent());
                                                ArrayList<String> strs = (ArrayList<String>) JsonUtils.stringToList(object.getJSONArray("items").toString(),String.class);
                                                config3.setSysinfoDisplay(strs);
                                                SLog.i(TAG,"config3---"+config3.toString());
                                                if(mIOnPcControlCallBack!=null){
                                                    mIOnPcControlCallBack.refreshShowData(config3.getSysinfoDisplay());
                                                }
                                            } catch (JSONException e) {
                                                SLog.d(TAG, "---Exception---" + e.getMessage());
                                            e.printStackTrace();
                                            }*/
                                            break;
                                        case "sysinfoDisplay":
                                              /*Cpu Temperature
                                                Gpu Temperature
                                                Cpu Frequency
                                                Gpu Frequency
                                                Cpu Usage
                                                Gpu Usage
                                                Cpu Power
                                                Gpu Power
                                                Date&Time*/

                                            try {
                                                JSONObject object = new JSONObject(serialData.getDataContent());
                                                ArrayList<String> strs = (ArrayList<String>) JsonUtils.stringToList(object.getJSONArray("items").toString(), String.class);
                                                if (mIOnPcControlCallBack != null) {
                                                    mIOnPcControlCallBack.refreshShowData(strs);
                                                }
                                            } catch (JSONException e) {
                                                SLog.d(TAG, "---Exception---" + e.getMessage());
                                                e.printStackTrace();
                                            }

                                            break;
                                        case "fanLCD":
                                            try {
                                                JSONObject jsonObject = new JSONObject(serialData.getDataContent());
                                                String fanSpeed = jsonObject.getString("speed");
                                                String fanMode = jsonObject.getString("mode");
                                                fanLCD.setSpeed(fanSpeed);
                                                fanLCD.setMode(fanMode);
                                                SLog.d(TAG, "fanLCD---speed--" + fanSpeed + "--mode--" + fanMode);

                                            } catch (JSONException e) {
                                                SLog.d(TAG, "---Exception---" + e.getMessage());
                                                e.printStackTrace();
                                            }
                                            break;
                                        case "fanLCDSet":
                                            //String str = "{"mode":"Smart Mode","smartMode":[[10,20],[30,50],[40,70],[55,85],[70,90],[90,100]],"fixedMode":80}"
                                            SLog.d(TAG, "---fanLCDSet---" + serialData.getDataContent());
                                            fanLCD = JsonUtils.stringToObject(serialData.getDataContent(), FanLCD.class);
                                            break;

                                        case "temperature":
                                            try {
                                                JSONObject jsonObject = new JSONObject(serialData.getDataContent());
                                                temp_unit = jsonObject.getString("value");
                                                SLog.d(TAG, "temp_unit--" + temp_unit);
                                            } catch (JSONException e) {
                                                SLog.d(TAG, "temperature JSONException--" + e.getMessage());
                                            }
                                            break;
                                        case "spec":
                                            try {
                                                JSONObject jsonObject = new JSONObject(serialData.getDataContent());
                                                cpuinfo = jsonObject.getString("cpu");
                                                gpuinfo = jsonObject.getString("gpu");
                                                if (mIOnPcControlCallBack != null) {
                                                    mIOnPcControlCallBack.nameTitleChange(cpuinfo,gpuinfo);
                                                }
                                                SLog.d(TAG, "cpuinfo--" + cpuinfo+"--gpuinfo--" + gpuinfo);
                                            } catch (JSONException e) {
                                                SLog.d(TAG, "temperature JSONException--" + e.getMessage());
                                            }
                                            break;
                                        case "rotate":
                                            try {
                                                JSONObject jsonObject = new JSONObject(serialData.getDataContent());
                                                int degree = jsonObject.getInt("degree");
                                                SystemPropertiesUtils.setProperty("persist.vendor.orientation",degree+"");
                                                SLog.d(TAG, "rotate--" + degree);
                                            } catch (JSONException e) {
                                                SLog.d(TAG, "temperature JSONException--" + e.getMessage());
                                            }
                                            break;
                                        case "config":
                                            try {
                                                JSONObject jsonObject = new JSONObject(serialData.getDataContent());
                                                temp_unit = jsonObject.getString("temperature");
                                                JSONObject waterBlockScreen = jsonObject.getJSONObject("waterBlockScreen");
                                                boolean enable = waterBlockScreen.getBoolean("enable");
                                                displayInSleep = waterBlockScreen.getBoolean("displayInSleep");
                                                int brightness = waterBlockScreen.getInt("brightness");
                                                ScreenConfig screenConfig = JsonUtils.stringToObject(
                                                        waterBlockScreen.getJSONObject("id").toString(),
                                                        ScreenConfig.class);
//                                                boolean waterfallMode = waterBlockScreen.getBoolean("waterfallMode");

                                                doBrightness(brightness);
                                                SLog.d(TAG, "temp_unit--" + temp_unit);
                                                JSONObject spexc = jsonObject.getJSONObject("spec");
                                                cpuinfo = spexc.getString("cpu");
                                                gpuinfo = spexc.getString("gpu");
                                                SLog.d(TAG, "cpuinfo--" + cpuinfo+"--gpuinfo--" + gpuinfo);

                                                if (mIOnPcControlCallBack != null) {
                                                    mIOnPcControlCallBack.screenConfigChange(screenConfig);
                                                }



                                                mReceiverHandler.postDelayed(new Runnable() {
                                                    @Override
                                                    public void run() {
                                                        doBlockScreen(enable);
                                                    }
                                                },1000);
                                                fanLCD = JsonUtils.stringToObject(
                                                        waterBlockScreen.getJSONObject("fanLCD").toString(), FanLCD.class);



                                            } catch (JSONException e) {
                                                SLog.d(TAG, "temperature JSONException--" + e.getMessage());
                                            }
                                            break;
                                        case "waterfallMode":
                                            try {
                                                JSONObject jsonObject = new JSONObject(serialData.getDataContent());
                                                boolean waterfallMode = jsonObject.getBoolean("enable");
                                                doWaterfallMode(waterfallMode);
                                            } catch (JSONException e) {
                                                SLog.d(TAG, "---Exception---" + e.getMessage());
                                                e.printStackTrace();
                                            }
                                            break;
                                    }
                                    break;

                            }
                            break;
                        case MSG_CONNECT_TIMEOUT:
                            SLog.d(TAG, "connect timeout--");
                            if (mIOnPcControlCallBack != null) {
                                mIOnPcControlCallBack.onDisConnect();
                                isTimeOut = true;
                            }
                            break;
                    }
                }
            };
            mReceiverHandler.removeMessages(MSG_CONNECT_TIMEOUT);
            mReceiverHandler.sendEmptyMessageDelayed(MSG_CONNECT_TIMEOUT, 1 * 60000);
            Looper.loop();
        }
    }


    public static MsgReceiverManager getInstance() {
        if (instance == null) instance = new MsgReceiverManager();
        return instance;
    }

    public void init(Context context, IOnPcControlCallBack onControlCallback) {
        MsgReceiverLooperThread msgReceiverLooperThread = new MsgReceiverLooperThread();
        msgReceiverLooperThread.start();
        mContext = context;
        this.mIOnPcControlCallBack = onControlCallback;
        SerialDataManage.getInstance().setOnDataChangeCallback(new IOnSerialDataCallback.Stub() {

            @Override
            public void onSerialDataChanged(SerialData data) throws RemoteException {
                SLog.d(TAG, "onSerialDataChanged---" + data.toString());

                Message message = new Message();
                message.what = MSG_RECEIVER_DATA;
                message.obj = data;
                mReceiverHandler.sendMessage(message);

                if (isTimeOut) {
                    isTimeOut = false;
                    if (mIOnPcControlCallBack != null) {
                        mIOnPcControlCallBack.onReConnect();
                    }
                }
                if (!isConnect) {
                    isConnect = true;
                    if (mIOnPcControlCallBack != null) {
                        mIOnPcControlCallBack.onConnected();
                    }
                }
                mReceiverHandler.removeMessages(MSG_CONNECT_TIMEOUT);
                mReceiverHandler.sendEmptyMessageDelayed(MSG_CONNECT_TIMEOUT, 1 * 60000);
            }

            @Override
            public void onFileUpload(String path) throws RemoteException {
                if (mIOnPcControlCallBack != null) {
                    mIOnPcControlCallBack.onFileUpload(path);
                }
            }
        });


    }

    private IOnPcControlCallBack mIOnPcControlCallBack;


    private void doBlockScreen(boolean event) {
        if (mIOnPcControlCallBack != null) {
            mIOnPcControlCallBack.onBlockScreen(event);
        }
    }

    private void doPower(String event) {
        if (mIOnPcControlCallBack != null) {
            mIOnPcControlCallBack.onDoPower(event);
        }
    }

    private void doBrightness(int brightness) {
        if (mIOnPcControlCallBack != null) {
            mIOnPcControlCallBack.onDoBrightness((int) (brightness * 2.5));
        }
    }

    private void doWaterfallMode(boolean enble) {
        if (mIOnPcControlCallBack != null) {
            mIOnPcControlCallBack.onWaterfallModeChange(enble);
        }
    }

    //获取设备剩余空间
    public static long getAvailableStorage() {
        File path = Environment.getExternalStorageDirectory();
        StatFs stat = new StatFs(path.getPath());
        long blockSize = stat.getBlockSizeLong();
        long availableBlocks = stat.getAvailableBlocksLong();
        return availableBlocks * blockSize;
    }


    public FanLCD getFanLCD() {
        if (fanLCD == null) {
            fanLCD = new FanLCD();
            fanLCD.setMode("Smart Mode");
            fanLCD.setSpeed("Mid Speed");
            fanLCD.setFixedMode(45);
        }
        return fanLCD;
    }


}
